package member

import (
	"errors"
	"lao-a/helper"
	"lao-a/models/model"
	"net/url"
	"strconv"
	"time"

	"github.com/astaxie/beego/validation"
	"github.com/yl10/kit/guid"
	"github.com/yl10/kit/orm"
)

const (
	MEMTYPE_PERSON     = "person"
	MEMTYPE_ENTERPRISE = "enterprise"
)

type CommonType struct {
	TypeId   string
	TypeName string
}

type MemberProfile struct {
	MemId string
	model.TaMember `xorm:"extends"`
	model.TaCardAccount `xorm:"extends"`
}

// DAO 当前数据库操作对象
type DAO struct {
	ctx *helper.Context
	db  *orm.XormPlus
}

// NewDAO 初始化DAO
func NewDAO(ctx *helper.Context) *DAO {
	return &DAO{
		ctx: ctx,
		db:  ctx.GetDB(),
	}
}

// 会员卡类型
func (m *DAO) GetMemberTypes() []CommonType {
	return []CommonType{
		CommonType{
			TypeId:   MEMTYPE_PERSON,
			TypeName: "个人",
		},
		CommonType{
			TypeId:   MEMTYPE_ENTERPRISE,
			TypeName: "企业",
		},
	}
}

// JoinClub 申请入会
func (m *DAO) JoinClub(params url.Values) (*model.TaMember, error) {
	mem := &model.TaMember{}
	if err := helper.UrlValues2XormModel(params, mem); err != nil {
		return nil, err
	}

	// 验证
	if err := m.checkNewMember(mem); err != nil {
		return nil, err
	}

	now := time.Now()
	mem.MemId = guid.NewGUIDString()
	mem.CreateDate = now

	return m.SaveMember(mem)
}

// InitMember 初始化会员及其相关账户信息
func (m *DAO) InitMember(params url.Values) (*model.TaMember, error) {
	// 会员ID
	memId := guid.NewGUIDString()
	mem := &model.TaMember{}
	if err := helper.UrlValues2XormModel(params, mem); err != nil {
		return nil, err
	}

	// 验证
	if err := m.checkNewMember(mem); err != nil {
		return nil, err
	}

	// 会员类型
	memType := params.Get("MemType")
	if memType == "" {
		memType = MEMTYPE_PERSON
	}

	cardType := CARD_PERSONAL
	if memType == MEMTYPE_ENTERPRISE {
		cardType = CARD_ENTERPRISE
	}

	// 会员卡
	cardNum := params.Get("CardNum")
	if cardNum == "" {
		return nil, helper.LogError("初始化会员失败, 卡号不能为空")
	}

	if _, err := m.InitCard(cardNum, cardType); err != nil {
		return nil, err
	}

	// 账户
	acc, err := m.InitAccount(cardNum, memId, memType)
	if err != nil {
		return nil, err
	}

	// 等级
	lvlId, _ := strconv.Atoi(params.Get("LevelId"))
	if lvlId == 0 {
		return nil, helper.LogError("初始化会员失败, 会员等级不能为空")
	}

	if acc.LevelId != lvlId {
		if err = m.UpdateAccount(acc.AccId, map[string]interface{}{
			"LevelId": lvlId,
		}); err != nil {
			return nil, err
		}
	}

	user := m.ctx.User.(*model.SysUser)
	now := time.Now()

	mem.MemId = memId
	mem.CreateDate = now
	mem.CreateUser = user.UserId

	return m.SaveMember(mem)
}

// SaveMember 保存成员
func (m *DAO) SaveMember(member *model.TaMember) (*model.TaMember, error) {
	if member.MemId == "" {
		member.MemId = guid.NewGUIDString()
	}

	_, err := m.db.Insert(member)
	return member, err
}

// GetMemberList 查询会员列表
func (m *DAO) GetMemberList() ([]MemberProfile, error) {
	var mems []MemberProfile
	if err := m.db.Table("ta_member").Alias("t").
		Join("INNER", []string{"ta_card_account", "s"}, "t.mem_id = s.mem_id").
		Desc("t.create_date").
		Find(&mems); err != nil {
		return nil, helper.LogError("查询会员列表失败", err)
	}

	return mems, nil
}

// GetMemberById 查询会员
func (m *DAO) GetMemberById(memId string) (*MemberProfile, error) {
	var mem MemberProfile
	if _, err := m.db.Table("ta_member").Alias("t").
		Join("INNER", []string{"ta_card_account", "s"}, "t.mem_id = s.mem_id").
		Where("t.mem_id=?", memId).
		Get(&mem); err != nil {
		return nil, helper.LogError("查询会员失败", err)
	}

	return &mem, nil
}

// UpdateMember 更新会员信息
func (m *DAO) UpdateMember(mem *model.TaMember, cols []string) error {
	_, err := m.db.Update(mem, cols, "mem_id=?", mem.MemId)

	if err != nil {
		return helper.LogError("更新会员信息失败", err)
	}

	return nil
}

// checkIdCardOrPhone 验证身份证或者手机号
func (m *DAO) checkIdCardOrPhone(idCard, phone string) error {
	mem := model.TaMember{}
	has, err := m.db.Where("id_card=?", idCard).Or("phone=?", phone).Count(&mem)

	if err != nil {
		return helper.LogError("验证身份证号或联系方式是否重复失败", err)
	}

	if has > 0 {
		return errors.New("该身份证号或手机号已经被注册")
	}

	return nil
}

func (m *DAO) checkNewMember(mem *model.TaMember) error {
	valid := validation.Validation{}
	valid.Required(mem.Name, "Name").Message("入会申请失败, 请填写姓名")
	valid.Required(mem.Phone, "Phone").Message("入会申请失败, 请填写联系方式")
	valid.Required(mem.IdCard, "IdCard").Message("入会申请失败, 请填写身份证号")
	if valid.HasErrors() {
		// 这里只返回了第一个验证失败的错误
		return valid.Errors[0]
	}

	// 验证身份证号码与手机号
	if err := m.checkIdCardOrPhone(mem.IdCard, mem.Phone); err != nil {
		return err
	}

	return nil
}
